﻿using OpenTK.Graphics.OpenGL4;
using StbImageSharp;
namespace TrinityEngine
{
    public class Texture : IDisposable
    {
        private bool _disposed = false;

        private int _rendererID;

        private byte[] _data;

        public Vector2 size => new Vector2(width, height);

        public int width { get; private set; }

        public int height { get; private set; }

        public Texture(string path)
        {
            StbImage.stbi_set_flip_vertically_on_load(1);

            ImageResult image = ImageResult.FromStream(File.OpenRead(path), ColorComponents.RedGreenBlueAlpha);
            _data = image.Data;
            width = image.Width;
            height = image.Height;

            _rendererID = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, _rendererID);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, _data);

            GL.GenerateTextureMipmap(_rendererID);
        }

        ~Texture()
        {
            Dispose(false);
        }

        public void Bind(int slot)
        {
            GL.ActiveTexture(TextureUnit.Texture0 + slot);
            GL.BindTexture(TextureTarget.Texture2D, _rendererID);
        }

        public void Unbind()
        {
            GL.BindTexture(TextureTarget.Texture2D, 0);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                _data = null;
            }

            GL.DeleteTexture(_rendererID);

            _disposed = true;
        }
    }
}
